#include "StdTcpServer.h"
StdTcpSocketPrivate::StdTcpSocketPrivate()
{
    memset(&serverAddress, 0, sizeof(serverAddress));
}

StdTcpSocketPrivate::~StdTcpSocketPrivate() {}


StdTcpSocket::StdTcpSocket() : m_sockfd(-1), m_connected(false)
{
    m_sockAttr = std::make_unique<StdTcpSocketPrivate>();
}

StdTcpSocket::~StdTcpSocket()
{
    if (m_sockfd != -1)
    {
        close(m_sockfd);
    }
}

int StdTcpSocket::connectToServer(const char *ip, int port)
{
    m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (m_sockfd == -1)
    {
        return -1;
    }

    m_sockAttr->serverAddress.sin_family = AF_INET;
    m_sockAttr->serverAddress.sin_port = htons(port);
    inet_pton(AF_INET, ip, &m_sockAttr->serverAddress.sin_addr);

    if (connect(m_sockfd, (struct sockaddr *)&m_sockAttr->serverAddress, sizeof(m_sockAttr->serverAddress)) == -1)
    {
        close(m_sockfd);
        return -1;
    }

    m_connected = true;
    return 0;
}

bool StdTcpSocket::isConnected() const
{
    return m_connected;
}

int StdTcpSocket::sendMessage(const std::string &sendMsg)
{
    if (!m_connected)
        return -1;
    return write(m_sockfd, sendMsg.c_str(), sendMsg.size());
}

int StdTcpSocket::sendMessage(const void *sendMessage, size_t n)
{
    if (!m_connected)
        return -1;
    return write(m_sockfd, sendMessage, n);
}

int StdTcpSocket::recvMessage(std::string &recvMessage)
{
    if (!m_connected)
        return -1;
    char buffer[1024];
    int bytesReceived = read(m_sockfd, buffer, sizeof(buffer));
    if (bytesReceived > 0)
    {
        recvMessage.assign(buffer, bytesReceived);
    }
    else
    {
        m_connected = false; 
    }
    return bytesReceived;
}

int StdTcpSocket::recvMessage(void *buf, size_t n)
{
    if (!m_connected)
        return -1;
    return read(m_sockfd, buf, n);
}

StdTcpSocketPrivate *StdTcpSocket::getSockAttr() const
{
    return m_sockAttr.get();
}


StdTcpServer::StdTcpServer() : m_port(0), m_listenfd(-1)
{
    m_tcpAttr = std::make_unique<StdTcpSocketPrivate>();
}

StdTcpServer::~StdTcpServer()
{
    if (m_listenfd != -1)
    {
        close(m_listenfd);
    }
}

bool StdTcpServer::setListen(int port)
{
    m_port = port;
    m_listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (m_listenfd == -1)
    {
        return false;
    }

    m_tcpAttr->serverAddress.sin_family = AF_INET;
    m_tcpAttr->serverAddress.sin_addr.s_addr = INADDR_ANY;
    m_tcpAttr->serverAddress.sin_port = htons(port);

    if (bind(m_listenfd, (struct sockaddr *)&m_tcpAttr->serverAddress, sizeof(m_tcpAttr->serverAddress)) == -1)
    {
        close(m_listenfd);
        return false;
    }

    if (listen(m_listenfd, SOMAXCONN) == -1)
    {
        close(m_listenfd);
        return false;
    }

    return true;
}

std::shared_ptr<StdTcpSocket> StdTcpServer::getclientsock()
{
    if (m_listenfd == -1)
    {
        return nullptr;
    }

    int clientfd = accept(m_listenfd, nullptr, nullptr);
    if (clientfd == -1)
    {
        return nullptr;
    }

    auto clientSock = std::make_shared<StdTcpSocket>();
    clientSock->m_sockfd = clientfd; 
    clientSock->m_connected = true;  
    return clientSock;
}
